/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hps.model;

import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.ImageIcon;

/**
 *
 * @author $Author: NIKE3500 $
 * @version $Revision: 85 $
 * @date $Date: 2013-01-14 18:59:09 +0000 (Mon, 14 Jan 2013) $
 */
public class Fire implements IInfluence
{
    //Konstanten

    public static final int STANDARD_SPREAD_TIME = 3;
    //static
    private static Image fireImage = null;
    //Member-Variablen
    private int ticksToSpread,
            ticks;
    private Point position;
    private ArrayList<IInfluence> me;
    private Point[] influenceArea;

    /**
     * Initialisiert ein neues Feuer mit Verbreitungsgeschwindigkeit und
     * Position
     *
     * @param ticksToSpread Controlerticks, bis Feuer sich aubreitet
     * @param position Position des Feuers
     */
    public Fire(int ticksToSpread, Point position)
    {
        this.ticksToSpread = ticksToSpread;
        this.ticks = 0;
        this.position = position;

        this.me = new ArrayList<IInfluence>();
        this.me.add(this);

        this.influenceArea = new Point[4];
        this.influenceArea[0] = new Point(position.getX(), position.getY() - 1);
        this.influenceArea[1] = new Point(position.getX(), position.getY() + 1);
        this.influenceArea[2] = new Point(position.getX() - 1, position.getY());
        this.influenceArea[3] = new Point(position.getX() + 1, position.getY());
    }

    /**
     * Verbreitet das Feuer. Das Feuer verbreitet sich nach oben, unten, links
     * und rechts, falls die dortigen Felder nicht blockiert sind.
     *
     * @param blocked Karte der blockierten Felder
     * @return Abkoemmlinge des Feuers
     */
    @Override
    public ArrayList<IInfluence> spread(IInfluence[][] blocked)
    {
        ArrayList<IInfluence> rtrn;

        if (++ticks < ticksToSpread)
        {
            rtrn = me;
        }
        else
        {
            rtrn = new ArrayList<IInfluence>();
            for (Point p : influenceArea)
            {
                if ((p.getX() >= 0) && (p.getY() >= 0)
                        && (blocked.length > p.getX())
                        && (blocked[0].length > p.getY())
                        && (blocked[p.getX()][p.getY()] == null))
                {
                    rtrn.add(new Fire(ticksToSpread, p));
                }
            }
        }

        return rtrn;
    }

    /**
     * Zeichenmethode des Feuers. Das Feuer malt eine kleine Flamme an seine
     * Position.
     *
     * @param g Zu nutzende Instanz von Graphics
     * @param roomPosition Ursprung der Raums auf dem Bild
     * @param singleFieldSize Pixelbreite eine Feldes
     */
    @Override
    public void draw(Graphics g, Point roomPosition, int singleFieldSize)
    {
        if (fireImage == null)
        {
            fireImage = new ImageIcon(getClass().getResource("/hps/view/HPS_icons/feuer.png")).getImage();
        }
        g.drawImage(fireImage,
                roomPosition.getX() + this.position.getX() * singleFieldSize + 1,
                roomPosition.getY() + this.position.getY() * singleFieldSize + 1,
                singleFieldSize, singleFieldSize, null);
    }

    /**
     * Setzt den Einfluss des Feuers. Ein Feuer stoesst Pdestrians ab.
     *
     * @param field
     */
    @Override
    public void setInfluence(FloorField field)
    {
        if (ticks == 0)
        {
            byte[][] byteField = field.getField();
            for (Point p : influenceArea)
            {
                if ((p.getX() >= 0)
                        && (p.getY() >= 0)
                        && (p.getX() < byteField.length)
                        && (p.getY() < byteField[0].length))
                {
                    byteField[p.getX()][p.getY()] -= byteField[p.getX()][p.getY()] < Byte.MIN_VALUE + 20 ? Byte.MIN_VALUE - byteField[p.getX()][p.getY()] : 20;
                }
            }
            field.setField(byteField);
        }
    }

    /**
     * Ein Feuer schadet Pedestrians oben, unten, links und rechts vom Feuer.
     * Der Pedestrians auf dem Feuer erhaelt extra schaden.
     *
     * @param pedestrians
     */
    @Override
    public void damage(ArrayList<Pedestrian> pedestrians)
    {
        ArrayList<Pedestrian> localPedestrians = (ArrayList<Pedestrian>)pedestrians.clone();
        for (Pedestrian p : localPedestrians)
        {
            for (Point pnt : influenceArea)
            {
                if (pnt.equals(p.getPos()))
                {
                    p.inflictDamage(pnt.equals(this.position) ? 30 : 20);
                }
            }
        }
    }

    @Override
    public IInfluence clone()
    {
        Fire rtrn = new Fire(ticksToSpread, position);
        rtrn.influenceArea = this.influenceArea.clone();
        return rtrn;
    }

    /**
     * Liefert die Position des Feuers zurueck
     *
     * @return Position des Feuers
     */
    public Point getPos()
    {
        return position.clone();
    }

    @Override
    public boolean isAt(Point pos)
    {
        return pos.equals(this.position);
    }

    @Override
    public int getBlocked(Point p)
    {
        return 0;
    }

    @Override
    public ArrayList<Point> getBlockedFields()
    {
        return new ArrayList<Point>();
    }

    @Override
    public boolean isBlocking()
    {
        return false;
    }

    @Override
    public boolean equals(Object o)
    {
        if (o == null)
        {
            return false;
        }
        if (!(o instanceof Fire))
        {
            return false;
        }
        if (!(o.hashCode() == this.hashCode()))
        {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode()
    {
        int hash = 5;
        hash = 83 * hash + this.ticksToSpread;
        hash = 83 * hash + this.ticks;
        hash = 83 * hash + (this.position != null ? this.position.hashCode() : 0);
        hash = 83 * hash + Arrays.deepHashCode(this.influenceArea);
        return hash;
    }
}
